﻿//#define DEBUG
#undef DEBUG

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Newtonsoft.Json;
using Lib;
using SocketChat.control;



namespace SocketChat
{
    /// <summary>
    /// by 菩提树下的杨过(yjmyzz@126.com) 允许用于商业用途，但请保留作者信息
    /// </summary>
    public partial class MainPage : UserControl
    {

        Socket skt;//客户端 Socket                       
        List<byte> lstReceiveBytes = new List<byte>(ConstParameter.BUFFER_SIZE);
        int _dataLength = 0;
        LengthType _dataType = LengthType.Unknown;

        string _InitGuestName = "游客" + new Random().Next(0, 9999).ToString().PadLeft(4, '0');
        string _localIPAndPort = "";


        public MainPage()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Page_Loaded);
        }

        void Page_Loaded(object sender, RoutedEventArgs e)
        {
            // 初始化姓名和需要发送的默认文字
            txtName.Text = _InitGuestName;
            //txtInput.Text = "大家好，新人报到，请多关照！";          

            TextBlock tbAll = new TextBlock() { Text = ConstParameter.BROADCAST_NAME };
            tbAll.SetValue(ToolTipService.ToolTipProperty, ConstParameter.BROADCAST_ENDPOINT);
            cboTarget.Items.Add(tbAll);
            cboTarget.SelectedIndex = 0;

            Connection();

        }

        /// <summary>
        /// 连接到scoket服务器
        /// </summary>
        void Connection()
        {
            try
            {
                if (skt == null)
                {
                    // 实例化 Socket
                    skt = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    skt.ReceiveBufferSize = ConstParameter.BUFFER_SIZE;
                    skt.SendBufferSize = ConstParameter.BUFFER_SIZE;
                    skt.NoDelay = true;
                }


                if (skt.Connected)
                {
                    OutPut("服务器当前已连接！");
                    return;
                }

                // 实例化 SocketAsyncEventArgs ，用于对 Socket 做异步操作，很方便
                SocketAsyncEventArgs args = new SocketAsyncEventArgs();
                // 服务器的 EndPoint
                args.RemoteEndPoint = new DnsEndPoint(txtServerIP.Text, 4518);
                // 异步操作完成后执行的事件
                args.Completed += new EventHandler<SocketAsyncEventArgs>(OnSocketConnectCompleted);

                // 异步连接服务端
                skt.ConnectAsync(args);

            }
            catch (Exception ex)
            {
                OutPut(ex.Message.ToString());
            }
        }

        /// <summary>
        /// 连接完成回调处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnSocketConnectCompleted(object sender, SocketAsyncEventArgs e)
        {
            try
            {
                //显示连接结果
                string initMsg = "";
                if (skt == null || !skt.Connected)
                {
                    initMsg = "无法连接到服务器...请刷新后再试...";
                }
                else
                {
                    initMsg = "成功地连接上了服务器...";

                    SocketAsyncEventArgs args = new SocketAsyncEventArgs();
                    args.RemoteEndPoint = e.RemoteEndPoint;

                    // 设置数据缓冲区
                    byte[] buffer = new byte[ConstParameter.BUFFER_SIZE];
                    args.SetBuffer(buffer, 0, buffer.Length);

                    args.Completed += new EventHandler<SocketAsyncEventArgs>(OnSocketReceiveCompleted);
                    // 异步地从服务端 Socket 接收数据
                    skt.ReceiveAsync(args);
                }

                OutPut(initMsg);

                //发送初始信息，以获得在线列表
                SendText("大家好，我是新来的，很高兴认识大家！");
            }
            catch (Exception ex)
            {
                OutPut(ex.Message.ToString());
            }
        }

        /// <summary>
        /// 发送完成后的回调函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void SendArgs_Completed(object sender, SocketAsyncEventArgs e)
        {
            //OutPut("发送结果：" + e.SocketError.ToString() + "，" + e.UserToken.ToString());
        }

        /// <summary>
        /// 接受服务端发来的数据-回调处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnSocketReceiveCompleted(object sender, SocketAsyncEventArgs e)
        {
            try
            {
#if DEBUG
                OutPut("OnSocketReceiveCompleted 成功" + DateTime.Now.ToString());
#endif
                if (e.BytesTransferred >= 5)
                {
                    if (e.Buffer[e.Offset] == ConstParameter.SPLIT_CHAR && e.Buffer[e.Offset + e.BytesTransferred - 1] == ConstParameter.SPLIT_CHAR)
                    {
                        string[] _lengthArr = UTF8Encoding.UTF8.GetString(e.Buffer, e.Offset + 1, e.BytesTransferred - 2).Split(ConstParameter.SPLIT_CHAR);

                        if (int.TryParse(_lengthArr[0], out _dataLength) == false)//异常情况
                        {
                            _dataLength = 0;
                            _dataType = LengthType.Unknown;
                            lstReceiveBytes.Clear();
                        }
                        else
                        {
                            _dataType = (LengthType)(int.Parse(_lengthArr[1]));
                        }
                    }
                    else
                    {
                        for (int i = e.Offset; i < e.Offset + e.BytesTransferred; i++)
                        {
                            lstReceiveBytes.Add(e.Buffer[i]);
                        }
                    }


                    if (lstReceiveBytes.Count == _dataLength) //收完了
                    {

                        string _jsonStr = Encoding.UTF8.GetString(lstReceiveBytes.ToArray(), 0, lstReceiveBytes.Count);

                        lstReceiveBytes.Clear();//清空，为下次接收做准备
                        _dataLength = 0;                       

                        if (_dataType == LengthType.ChatMessage)
                        {
                            #region 
                            ChatMessage msg = JsonConvert.DeserializeObject<ChatMessage>(_jsonStr);

                            if (!string.IsNullOrEmpty(msg.SenderIPAndPort))
                            {
                                if (_localIPAndPort == "")
                                {
                                    _localIPAndPort = msg.SenderIPAndPort;
                                }
                            }

                            string _content = "";
                            switch (msg.Type)
                            {
                                case ChatMessage.MessageType.txt:
                                    _content = UTF8Encoding.UTF8.GetString(msg.Body, 0, msg.Body.Length);
                                    OutPutText(msg, _content);
                                    break;
                                case ChatMessage.MessageType.img:
                                    MemoryStream msImg = new MemoryStream();
                                    msImg.Write(msg.Body, 0, msg.Body.Length);
                                    OutPutImage(msImg, msg);
                                    break;
                                case ChatMessage.MessageType.file:
                                    MemoryStream msFile = new MemoryStream();
                                    msFile.Write(msg.Body, 0, msg.Body.Length);
                                    OutPutFile(msFile, msg.SenderName, msg.FileName);
                                    break;
                                //case ChatMessage.MessageType.wb:
                                //    MemoryStream msWb = new MemoryStream();
                                //    msWb.Write(msg.Body, 0, msg.Body.Length);                            
                                //    OutPutWb(msWb, msg);
                                //    break;
                                case ChatMessage.MessageType.unknown:
                                default:
                                    OutPut("服务端消息接收成功，但无法认别内容!");
                                    break;
                            }
                            #endregion
                        }
                        else if (_dataType == LengthType.ChatUser)
                        {
                            #region
                            //xml = new XmlSerializer(typeof(List<ChatUser>));
                            //List<ChatUser> lstOnlineUser = xml.Deserialize(ms) as List<ChatUser>;

                            //JsonArray jsonArr = jsonv as JsonArray;

                            //List<ChatUser> lstOnlineUser = new List<ChatUser>();

                            //foreach (JsonValue obj in jsonArr)
                            //{
                            //    lstOnlineUser.Add(new ChatUser() { EndPoint = obj["EndPoint"].ToString().Trim('"'), NickName = obj["NickName"].ToString().Trim('"'), UserId = new Guid(obj["UserId"].ToString().Trim('"')) });
                            //}

                            List<ChatUser> lstOnlineUser = JsonConvert.DeserializeObject<List<ChatUser>>(_jsonStr);

                            if (lstOnlineUser.Count>0)
                            {
                                this.Dispatcher.BeginInvoke(() =>
                                {
                                    lstOnline.ItemsSource = lstOnlineUser;
                                    lstOnlineUser.Insert(0, new ChatUser() { EndPoint = ConstParameter.BROADCAST_ENDPOINT, NickName = ConstParameter.BROADCAST_NAME, UserId = Guid.Empty });
                                    int _temp = cboTarget.SelectedIndex;
                                    if (cboTarget.Items.Count == 1 && cboTarget.Items[0] is TextBlock)
                                    {
                                        cboTarget.Items.Clear();//绑定一次后，这里居然变成"只读"了，所以暂时只能这样处理
                                    }
                                    cboTarget.ClearValue(ComboBox.ItemsSourceProperty);
                                    cboTarget.ItemsSource = lstOnlineUser;
                                    cboTarget.SelectedIndex = _temp;
                                });
                            }
                            else
                            {
                                this.Dispatcher.BeginInvoke(() =>
                                {
                                    lstOnline.Items.Clear();
                                    lstOnline.Items.Add(new TextBlock() { Text = "用户列表刷新失败!" });
                                });
                            }
                            #endregion
                        }
                    }
                    else if (lstReceiveBytes.Count > _dataLength) //异常情况(粘包)
                    {
                        lstReceiveBytes.Clear();//清空，为下次接收做准备
                        _dataLength = 0;
#if DEBUG
                        OutPut("接收信息失败！lstReceiveBytes.Count=" + lstReceiveBytes.Count + "，_dataLength=" + _dataLength);
#endif
                    }
                }


            }
            catch (Exception ex)
            {
                OutPut(ex.Message.ToString());
            }

            try
            {
                //继续异步地从服务端 Socket 接收数据(类似长连接)
                if (skt != null && skt.Connected)
                {
                    skt.ReceiveAsync(e);
                }
                else
                {
                    OutPut("无法连接到服务器...请刷新后再试...");
                }
            }
            catch (Exception ex)
            {
                OutPut(ex.Message.ToString());
            }

#if DEBUG
            //Thread.Sleep(1000);
#endif

        }

        /// <summary>
        /// 接收文本后的显示
        /// </summary>
        /// <param name="data"></param>
        private void OutPut(string data)
        {
            //在聊天文本框中输出指定的信息，并将滚动条滚到底部
            this.Dispatcher.BeginInvoke(
                delegate
                {
                    lstChat.Items.Add(new TextBlock() { Text = data, TextWrapping = TextWrapping.Wrap });
                    scrollChat.ScrollToVerticalOffset(lstChat.ActualHeight + 50.0);//不知道为啥，这一行不起作用
                }
            );
        }

        private void OutPutText(ChatMessage msg, string content)
        {
            //在聊天文本框中输出指定的信息，并将滚动条滚到底部
            this.Dispatcher.BeginInvoke(
                delegate
                {
                    TextBlock tb = new TextBlock() { TextWrapping = TextWrapping.Wrap };

                    if (_localIPAndPort == msg.SenderIPAndPort)
                    {
                        tb.Inlines.Add("我 ");
                    }
                    else
                    {
                        tb.Inlines.Add(msg.SenderName + " ");
                    }

                    tb.Inlines.Add(new Run() { Text = DateTime.Now.ToString(), Foreground = new SolidColorBrush(Colors.Gray) });


                    tb.Inlines.Add(" 对 " + msg.ReceiverName + " 说：");



                    tb.Inlines.Add(new LineBreak());
                    tb.Inlines.Add(new Run() { Text = content, Foreground = new SolidColorBrush(Tool.GetColorFromString(msg.Color)) });

                    lstChat.Items.Add(tb);
                    scrollChat.ScrollToVerticalOffset(lstChat.ActualHeight + 50.0);//不知道为啥，这一行不起作用         

                }
            );
        }

        /// <summary>
        /// 接收图片后的显示
        /// </summary>
        /// <param name="sm"></param>
        /// <param name="name"></param>
        private void OutPutImage(Stream sm, ChatMessage msg)
        {
            this.Dispatcher.BeginInvoke(
                delegate
                {
                    TextBlock tb = new TextBlock() { TextWrapping = TextWrapping.Wrap };
                    tb.Inlines.Add(msg.SenderName + " ");
                    tb.Inlines.Add(new Run() { Text = DateTime.Now.ToString(), Foreground = new SolidColorBrush(Colors.Gray) });
                    tb.Inlines.Add(" 给 " + msg.ReceiverName + " 发送了图片“");
                    tb.Inlines.Add(new Run() { Text = msg.FileName, Foreground = new SolidColorBrush(Tool.GetColorFromString(msg.Color)) });
                    tb.Inlines.Add("”：");
                    lstChat.Items.Add(tb);
                    Image img = new Image();
                    BitmapImage bitmap = new BitmapImage();
                    bitmap.SetSource(sm);
                    img.Source = bitmap;
                    img.Stretch = System.Windows.Media.Stretch.None;
                    lstChat.Items.Add(img);
                    scrollChat.ScrollToVerticalOffset(lstChat.ActualHeight);
                    sm.Close();
                }
            );
        }

        private void OutPutWb(MemoryStream sm, ChatMessage msg)
        {
            this.Dispatcher.BeginInvoke(
                delegate
                {
                    TextBlock tb = new TextBlock() { TextWrapping = TextWrapping.Wrap };
                    tb.Inlines.Add(msg.SenderName + " ");
                    tb.Inlines.Add(new Run() { Text = DateTime.Now.ToString(), Foreground = new SolidColorBrush(Colors.Gray) });
                    tb.Inlines.Add(" 给 " + msg.ReceiverName + " 发送了图片“");
                    tb.Inlines.Add(new Run() { Text = msg.FileName, Foreground = new SolidColorBrush(Tool.GetColorFromString(msg.Color)) });
                    tb.Inlines.Add("”：");
                    lstChat.Items.Add(tb);

                    try
                    {
                        BitmapImage bi = new BitmapImage();
                        bi.SetSource(sm);

                        Image img = new Image();
                        img.Source = bi;

                        img.Stretch = System.Windows.Media.Stretch.None;
                        lstChat.Items.Add(img);
                    }
                    catch (Exception ex) 
                    {
                        OutPut(ex.Message.ToString());
                    }

                    scrollChat.ScrollToVerticalOffset(lstChat.ActualHeight);
                    sm.Close();
                }
            );
        }

        /// <summary>
        /// 接收文件后的显示
        /// </summary>
        /// <param name="sm"></param>
        /// <param name="name"></param>
        private void OutPutFile(Stream sm, string senderName, string fileName)
        {
            this.Dispatcher.BeginInvoke(
                delegate
                {

                    lstChat.Items.Add(new TextBlock() { Text = senderName + " [" + DateTime.Now.ToString() + "]发送了文件“" + fileName + "”，是否保存?" });
                    StackPanel sp = new StackPanel() { Orientation = Orientation.Horizontal };

                    FileSaveButton btnYes = new FileSaveButton(fileName, sm as MemoryStream) { Content = "保存" };
                    Button btnNo = new Button() { Content = "拒绝", Margin = new Thickness(5, 0, 0, 0) };

                    btnYes.Click += new RoutedEventHandler(btnYes_Click);
                    btnNo.Click += new RoutedEventHandler(btnNo_Click);

                    sp.Children.Add(btnYes);
                    sp.Children.Add(btnNo);

                    lstChat.Items.Add(sp);

                    scrollChat.ScrollToVerticalOffset(lstChat.ActualHeight);
                }
            );
        }

        void btnNo_Click(object sender, RoutedEventArgs e)
        {
            StackPanel pnl = (sender as Button).Parent as StackPanel;
            pnl.Children.Clear();
            pnl.Children.Add(new TextBlock() { Text = "您已经拒绝了该文件！" });

        }

        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void btnYes_Click(object sender, RoutedEventArgs e)
        {

            FileSaveButton btn = sender as FileSaveButton;

            string _ext = "txt";

            _ext = Path.GetExtension(btn.FileName).Trim('.');


            SaveFileDialog _saveDlg = new SaveFileDialog()
            {
                DefaultExt = _ext,
                Filter = _ext + " files (*." + _ext + ")|*." + _ext + "|All files (*.*)|*.*",
                FilterIndex = 1
            };

            if (_saveDlg.ShowDialog().Value)
            {
                using (Stream stream = _saveDlg.OpenFile())
                {
                    byte[] bFile = btn.Stream.ToArray();
                    btn.Stream.Close();
                    stream.Write(bFile, 0, bFile.Length);
                    stream.Close();
                }
                StackPanel pnl = (sender as Button).Parent as StackPanel;
                pnl.Children.Clear();
                pnl.Children.Add(new TextBlock() { Text = "您已经将文件保存为“" + _saveDlg.SafeFileName + "”" });
            }


        }

        /// <summary>
        /// 发送文件
        /// </summary>
        void SendFile()
        {
            if (skt != null && skt.Connected)
            {
                OpenFileDialog openFileDialog = new OpenFileDialog()
                {
                    Filter = "All Files(*.*)|*.*",
                    Multiselect = false
                };

                if (openFileDialog.ShowDialog().Value)
                {
                    FileInfo _fileInfo = openFileDialog.File;

                    if (_fileInfo.Length >= 1024 * 1024 * 5)
                    {
                        MessageBox.Show("此为演示，最大仅允许发送5M以内的文件!");
                        return;
                    }

                    FileStream _fs = _fileInfo.OpenRead();

                    byte[] arrFile = new byte[_fs.Length];
                    BinaryReader _reader = new BinaryReader(_fs);
                    _reader.Read(arrFile, 0, arrFile.Length);
                    _fs.Close();
                    _fs = null;

                    #region 封装要发送的数据
                    ChatMessage msg = new ChatMessage();
                    msg.SenderName = txtName.Text.Trim();
                    msg.Type = ChatMessage.MessageType.file;
                    msg.Body = arrFile;
                    //msg.ReceiverName = "All";
                    msg.FileName = _fileInfo.Name;

                    object obj = cboTarget.SelectedItem;
                    if (obj is TextBlock)
                    {
                        msg.ReceiverName = (cboTarget.SelectedItem as TextBlock).Text;
                        msg.ReceiverIPAndPort = (cboTarget.SelectedItem as TextBlock).GetValue(ToolTipService.ToolTipProperty).ToString();
                    }
                    else
                    {
                        msg.ReceiverName = (cboTarget.SelectedItem as ChatUser).NickName;
                        msg.ReceiverIPAndPort = (cboTarget.SelectedItem as ChatUser).EndPoint;
                    }

                    if (!chkSingle.IsChecked.Value)
                    {
                        msg.ReceiverIPAndPort = ConstParameter.BROADCAST_ENDPOINT;
                    }
                    msg.SenderIPAndPort = _localIPAndPort;
                    msg.Color = (colorSelect.rColor.Fill as SolidColorBrush).Color.ToString();
                    #endregion

                    Send(msg);
                }
            }
            else
            {
                OutPut("无法连接到服务器...请刷新后再试...");
            }


        }

        /// <summary>
        /// 发送图片
        /// </summary>
        void SendImage()
        {
            try
            {
                if (skt != null && skt.Connected)
                {
                    OpenFileDialog openFileDialog = new OpenFileDialog()
                    {
                        Filter = "Jpeg Files (*.jpg)|*.jpg|Png Files (*.png)|*.png",
                        Multiselect = false,
                        FilterIndex = 1
                    };

                    if (openFileDialog.ShowDialog().Value)
                    {
                        FileInfo _fileInfo = openFileDialog.File;


                        if (_fileInfo.Length >= 1024 * 300)
                        {
                            MessageBox.Show("此为演示，最大仅允许发送300k以内的图片!");
                            return;
                        }

                        string _ext = _fileInfo.Extension.ToLower().Trim();




                        if (!(_ext == ".jpg" || _ext == ".jpeg" || _ext == ".png"))
                        {
                            MessageBox.Show("仅支持jpg，png格式的图片！");
                            return;
                        }

                        FileStream _fs = _fileInfo.OpenRead();


                        byte[] arrImage = new byte[_fs.Length];
                        BinaryReader _reader = new BinaryReader(_fs);
                        _reader.Read(arrImage, 0, arrImage.Length);
                        _fs.Close();
                        _fs = null;

                        #region 封装要发送的数据
                        ChatMessage msg = new ChatMessage();
                        msg.SenderName = txtName.Text.Trim();
                        msg.Type = ChatMessage.MessageType.img;
                        msg.Body = arrImage;
                        //msg.ReceiverName = "All";
                        msg.FileName = _fileInfo.Name;

                        object obj = cboTarget.SelectedItem;
                        if (obj is TextBlock)
                        {
                            msg.ReceiverName = (cboTarget.SelectedItem as TextBlock).Text;
                            msg.ReceiverIPAndPort = (cboTarget.SelectedItem as TextBlock).GetValue(ToolTipService.ToolTipProperty).ToString();
                        }
                        else
                        {
                            msg.ReceiverName = (cboTarget.SelectedItem as ChatUser).NickName;
                            msg.ReceiverIPAndPort = (cboTarget.SelectedItem as ChatUser).EndPoint;
                        }

                        if (!chkSingle.IsChecked.Value)
                        {
                            msg.ReceiverIPAndPort = ConstParameter.BROADCAST_ENDPOINT;
                        }

                        msg.Color = (colorSelect.rColor.Fill as SolidColorBrush).Color.ToString();
                        msg.SenderIPAndPort = _localIPAndPort;
                        #endregion

                        Send(msg);

                    }
                }
                else
                {
                    OutPut("无法连接到服务器...请刷新后再试...");
                }
            }
            catch (Exception ex)
            {
                OutPut(ex.Message.ToString());
            }
        }


        public void SendImage(WriteableBitmap wb)
        {
            try
            {
                if (skt != null && skt.Connected)
                {
                    string _wbBase64String = Tool.GetBase64Image(wb);                   

                    byte[] arrImage = Convert.FromBase64String(_wbBase64String);                   

                    #region 封装要发送的数据
                    ChatMessage msg = new ChatMessage();
                    msg.SenderName = txtName.Text.Trim();
                    msg.Type = ChatMessage.MessageType.img;
                    msg.Body = arrImage;
                    //msg.ReceiverName = "All";
                    msg.FileName = "未命名";

                    object obj = cboTarget.SelectedItem;
                    if (obj is TextBlock)
                    {
                        msg.ReceiverName = (cboTarget.SelectedItem as TextBlock).Text;
                        msg.ReceiverIPAndPort = (cboTarget.SelectedItem as TextBlock).GetValue(ToolTipService.ToolTipProperty).ToString();
                    }
                    else
                    {
                        msg.ReceiverName = (cboTarget.SelectedItem as ChatUser).NickName;
                        msg.ReceiverIPAndPort = (cboTarget.SelectedItem as ChatUser).EndPoint;
                    }

                    if (!chkSingle.IsChecked.Value)
                    {
                        msg.ReceiverIPAndPort = ConstParameter.BROADCAST_ENDPOINT;
                    }

                    msg.Color = (colorSelect.rColor.Fill as SolidColorBrush).Color.ToString();
                    msg.SenderIPAndPort = _localIPAndPort;
                    #endregion

                    Send(msg);
                }
                else
                {
                    OutPut("无法连接到服务器...请刷新后再试...");
                }
            }
            catch (Exception ex)
            {
                OutPut(ex.Message.ToString());
            }
        }

        [ScriptableMember()]
        public void SendImage(string base64string) 
        {
            if (base64string.Length > 0) 
            {
                try 
                {
                    byte[] b = Convert.FromBase64String(base64string);
                    MemoryStream ms = new MemoryStream(b);
                    BitmapImage bi = new BitmapImage();
                    bi.SetSource(ms);
                    WriteableBitmap wb = new WriteableBitmap(bi as BitmapSource);
                    SendImage(wb);
                }
                catch (Exception ex) 
                {
                    
#if DEBUG
               OutPut(ex.Message.ToString());     
#endif
                }
            }
        }

        /// <summary>
        /// 发送文本消息
        /// </summary>
        void SendText()
        {
            if (txtName.Text.Trim().Length <= 0)
            {
                MessageBox.Show("用户呢称不能为空!");
                txtName.Focus();
                return;
            }

            if (txtInput.Text.Trim().Length <= 0)
            {
                MessageBox.Show("请输入发送的消息内容!");
                txtInput.Focus();
                return;
            }
            else if (txtInput.Text.Length > 10240)
            {
                MessageBox.Show("发送的消息不能超过1w字!");
                return;
            }

            if (skt != null && skt.Connected)
            {
                #region 封装要发送的数据
                ChatMessage msg = new ChatMessage();
                msg.SenderName = txtName.Text.Trim();
                msg.Type = ChatMessage.MessageType.txt;
                msg.Body = UTF8Encoding.UTF8.GetBytes(txtInput.Text.Trim());
                object obj = cboTarget.SelectedItem;
                if (obj is TextBlock)
                {
                    msg.ReceiverName = (cboTarget.SelectedItem as TextBlock).Text;
                    msg.ReceiverIPAndPort = (cboTarget.SelectedItem as TextBlock).GetValue(ToolTipService.ToolTipProperty).ToString();
                }
                else
                {
                    msg.ReceiverName = (cboTarget.SelectedItem as ChatUser).NickName;
                    msg.ReceiverIPAndPort = (cboTarget.SelectedItem as ChatUser).EndPoint;
                }

                if (!chkSingle.IsChecked.Value)
                {
                    msg.ReceiverIPAndPort = ConstParameter.BROADCAST_ENDPOINT;
                }
                msg.SenderIPAndPort = _localIPAndPort;

                msg.Color = (colorSelect.rColor.Fill as SolidColorBrush).Color.ToString();
                #endregion

                Send(msg);
            }
            else
            {
                OutPut("无法连接到服务器...请刷新后再试...");
            }

            txtInput.Focus();
            txtInput.Text = "";
        }

        void SendText(string Hello)
        {
            if (skt != null && skt.Connected)
            {
                #region 封装要发送的数据
                ChatMessage msg = new ChatMessage();
                msg.SenderName = _InitGuestName;
                msg.Type = ChatMessage.MessageType.txt;
                msg.Body = UTF8Encoding.UTF8.GetBytes(Hello);

                msg.ReceiverIPAndPort = ConstParameter.BROADCAST_ENDPOINT;
                msg.ReceiverName = ConstParameter.BROADCAST_NAME;
                msg.Color = "#FFFF0000";
                #endregion

                Send(msg);
            }
            else
            {
                OutPut("无法连接到服务器...请刷新后再试...");
            }

            //txtInput.Focus();
            //txtInput.Text = "";
        }

        private void btnSetServer_Click(object sender, RoutedEventArgs e)
        {
            Connection();
        }

        private void btnSendMsg_Click(object sender, RoutedEventArgs e)
        {
            SendText();
        }

        private void btnSendImg_Click(object sender, RoutedEventArgs e)
        {
            SendImage();
        }

        private void btnSendFile_Click(object sender, RoutedEventArgs e)
        {
            SendFile();
        }

        private void txtInput_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                SendText();
            }
        }

        private void btnClear_Click(object sender, RoutedEventArgs e)
        {
            this.Dispatcher.BeginInvoke(() => { this.lstChat.Items.Clear(); });
        }

        private void btnRefresh_Click(object sender, RoutedEventArgs e)
        {
            HtmlPage.Window.Navigate(HtmlPage.Document.DocumentUri);
        }

        private void UserControl_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
        {

            try
            {
                txtInput.Width = this.ActualWidth - 650;
                lstOnline.Height = this.ActualHeight - 230;
            }
            catch (Exception ex)
            {
                OutPut(ex.Message.ToString());
            }

        }

        /// <summary>
        /// 发送ChatMessage对象
        /// </summary>
        /// <param name="msg"></param>
        void Send(ChatMessage msg)
        {
            try
            {
                //MemoryStream ms = new MemoryStream();
                //DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ChatMessage));
                //ser.WriteObject(ms, msg);
                string _msgJsonString = JsonConvert.SerializeObject(msg);
                byte[] arrMsg = Encoding.UTF8.GetBytes(_msgJsonString);
//#if DEBUG
                //string _temp = Encoding.UTF8.GetString(arrMsg,0,arrMsg.Length);
//#endif

                //ms.Close();

                #region //先发送长度
                List<byte> lstLength = new List<byte>();
                lstLength.AddRange(UTF8Encoding.UTF8.GetBytes(ConstParameter.SPLIT_CHAR + arrMsg.Length.ToString() + ConstParameter.SPLIT_CHAR));
                List<ArraySegment<byte>> _lstLength = new List<ArraySegment<byte>>();
                _lstLength.Add(new ArraySegment<byte>(lstLength.ToArray()));
                SocketAsyncEventArgs SendArgs1 = new SocketAsyncEventArgs();
                SendArgs1.RemoteEndPoint = skt.RemoteEndPoint;
                SendArgs1.Completed += new EventHandler<SocketAsyncEventArgs>(SendArgs_Completed);
                SendArgs1.BufferList = _lstLength;
                skt.SendAsync(SendArgs1);
                #endregion

                System.Threading.Thread.Sleep(50);

                #region //再发送数据
                List<byte> lstSend = new List<byte>();
                lstSend.AddRange(arrMsg);
                List<ArraySegment<byte>> _lst = new List<ArraySegment<byte>>();
                _lst.Add(new ArraySegment<byte>(lstSend.ToArray()));
                SocketAsyncEventArgs SendArgs = new SocketAsyncEventArgs();
                SendArgs.RemoteEndPoint = skt.RemoteEndPoint;
                SendArgs.Completed += new EventHandler<SocketAsyncEventArgs>(SendArgs_Completed);
                SendArgs.BufferList = _lst;
                skt.SendAsync(SendArgs);
                #endregion

                Thread.Sleep(600);//每次发送完停一会儿，避免下次发送时“粘包”

            }
            catch (Exception ex)
            {
                OutPut(ex.Message.ToString());
            }
        }

        private void btnClose_Click(object sender, RoutedEventArgs e)
        {
            if (skt != null)
            {
                try
                {
                    skt.Close();
                    OutPut("服务器连接已断开...");
                    skt = null;
                }
                catch { }
            }
        }

        private void txtAuthor_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            HtmlPage.Window.Navigate(new Uri("http://www.cnblogs.com/yjmyzz/archive/2009/12/14/1623701.html"), "_blank");
        }

        private void cboTarget_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if ((sender as ComboBox).SelectedIndex == 0)
            {
                chkSingle.IsChecked = false;
                chkSingle.IsEnabled = false;
            }
            else
            {
                //chkSingle.IsChecked = ;
                chkSingle.IsEnabled = true;
            }
        }

        private void lstOnline_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if ((sender as ListBox).SelectedIndex != -1)
            {
                cboTarget.SelectedIndex = (sender as ListBox).SelectedIndex + 1;
            }
        }

        private void imgCapture_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            HtmlPage.Window.Invoke("fnCapture", "");
        }

        private void bdrInk_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            ChildWindow cw = new ChildWindow();
            cw.Title = "手写板";
            cw.Content = new InkWrite();
            cw.Width = 670.0;
            cw.Height = 340.0;
            cw.Show();
        }


        

    }
}